<template>
  <div
    v-if="banner?.show"
    class="w-full h-auto"
    :class="{
      'cursor-pointer': edit ?? true,
      'preview-block-active': (edit ?? true) && isActive
    }"
    @click="handlePreviewClick"
  >
    <div class="relative w-full bg-[#E1E2ED] overflow-hidden">
      <div v-if="!bannerUrl" class="flex-center w-full h-[500px]">
        <el-empty :image-size="200" :description="$t('competition.modules.banner.addBanner')" />
      </div>
      <div v-else class="w-full relative">
        <!-- 响应式Banner容器 -->
        <div
          ref="bannerContainerRef"
          class="relative w-full overflow-hidden"
          :style="containerStyle"
        >
          <!-- 响应式背景图片 -->
          <img
            v-if="imageLoaded"
            ref="backgroundImageRef"
            :src="imageUrl"
            alt="banner"
            class="w-full h-full object-cover"
            @load="handleImageLoad"
            @error="handleImageError"
          />

          <!-- 加载状态 -->
          <div v-if="imageLoading" class="absolute inset-0 flex items-center justify-center bg-gray-100">
            <div class="text-gray-500">图片加载中...</div>
          </div>

          <!-- 可拖拽按钮 -->
          <div
            v-if="buttonVisible && imageLoaded"
            ref="buttonRef"
            class="absolute px-[24px] py-[9px] rounded-[100px] border-none"
            :class="{ 'cursor-move': edit, 'cursor-pointer': !edit }"
            :style="buttonStyle"
            @mousedown="handleButtonMouseDown"
            @click="handleButtonClick"
          >
            {{ buttonText }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { computed, ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { $t } from '#/locales'
import { getImgUrl } from '#/utils/getImgUrl'
import { bufferToBase64 } from '#/utils/bufferToBase64'

const emit = defineEmits<{
  (e: 'update:banner', v: any): void;
  (e: 'click'): void;
}>()
const props = defineProps<{
  banner: any;
  edit?: boolean;
  isActive?: boolean;
}>()

// Vue Router 实例
const router = useRouter()

// 设计基准尺寸（固定）
const DESIGN_WIDTH = 1120
const DESIGN_HEIGHT = 560

// 组件引用
const bannerContainerRef = ref<HTMLDivElement>()
const backgroundImageRef = ref<HTMLImageElement>()
const buttonRef = ref<HTMLDivElement>()

// 状态管理
const imageLoading = ref(false)
const imageLoaded = ref(false)
const imageUrl = ref('')

// 图片和容器尺寸
const containerDimensions = ref({ width: 0, height: 0 })
const imageDimensions = ref({ width: 0, height: 0 })
const scale = ref(1)

// 拖拽状态
const isDragging = ref(false)

// Banner图片地址
const bannerUrl = computed(() => props.banner?.bannerUrl || '')

// 按钮文字
const buttonText = computed(() => props.banner?.button?.text || $t('competition.modules.banner.signUpNow'))

// 按钮是否显示
const buttonVisible = computed(() => {
  return !!bannerUrl.value &&
         (props.banner?.button?.show !== false) &&
         !!buttonText.value
})

// 按钮颜色
const buttonColor = computed(() => props.banner?.button?.color || '#E54D56')

// 按钮位置和样式配置
const buttonConfig = computed(() => {
  const button = props.banner?.button || {}
  const textStyle = button.textStyle || {}

  return {
    // 使用 ?? 而不是 || 来正确处理 0 值坐标
    x: button.x ?? 300,
    y: button.y ?? 410,
    fontSize: textStyle.fontSize || 16,
    fontColor: textStyle.fontColor || '#ffffff',
    fontBold: textStyle.fontBold || false,
    italic: textStyle.italic || false,
    underline: textStyle.underline || false
  }
})

// 容器样式（响应式高度基于实际图片比例）
const containerStyle = computed(() => {
  const { height } = containerDimensions.value
  return {
    width: '100%',
    height: height > 0 ? `${height}px` : 'auto',
    minHeight: '200px'
  }
})

// 按钮样式（基于实际缩放比例）
const buttonStyle = computed(() => {
  const config = buttonConfig.value
  const currentScale = scale.value

  return {
    left: `${config.x * currentScale}px`,
    top: `${config.y * currentScale}px`,
    background: buttonColor.value,
    color: config.fontColor,
    fontSize: `${config.fontSize * currentScale}px`,
    fontWeight: config.fontBold ? '600' : '400',
    fontStyle: config.italic ? 'italic' : 'normal',
    textDecoration: config.underline ? 'underline' : 'none',
    padding: `${9 * currentScale}px ${24 * currentScale}px`,
    whiteSpace: 'nowrap',
    userSelect: 'none',
    zIndex: isDragging.value ? 1000 : 10,
    transition: isDragging.value ? 'none' : 'all 0.2s ease',
    transform: 'translate(-50%, -50%)', // 中心点定位
    transformOrigin: 'center'
  } as const
})

// 图片加载处理
const loadImage = async (url: string) => {
  if (!url) {
    imageUrl.value = ''
    imageLoaded.value = false
    return
  }

  try {
    imageLoading.value = true
    const src = await getImgUrl(url) as any
    const base64Content = bufferToBase64(src)
    imageUrl.value = base64Content
    imageLoaded.value = true
  } catch (error) {
    console.error($t('competition.validation.imageLoadFailed'), error)
    imageUrl.value = ''
    imageLoaded.value = false
  } finally {
    imageLoading.value = false
  }
}

// 图片加载完成处理 - 计算真实的响应式尺寸
const handleImageLoad = () => {
  if (!backgroundImageRef.value || !bannerContainerRef.value) return

  const img = backgroundImageRef.value
  const container = bannerContainerRef.value

  // 获取图片原始尺寸
  imageDimensions.value = {
    width: img.naturalWidth,
    height: img.naturalHeight
  }

  // 计算容器尺寸（保持图片宽高比，宽度100%填充）
  const containerWidth = container.clientWidth
  const aspectRatio = img.naturalHeight / img.naturalWidth
  const containerHeight = containerWidth * aspectRatio

  containerDimensions.value = {
    width: containerWidth,
    height: containerHeight
  }

  // 计算缩放比例（基于设计基准尺寸）
  scale.value = containerWidth / DESIGN_WIDTH
}

// 图片加载错误处理
const handleImageError = () => {
  console.error($t('competition.validation.imageLoadFailed'))
  imageLoaded.value = false
}

// 重新计算尺寸（窗口大小变化时调用）
const recalculateDimensions = () => {
  if (backgroundImageRef.value && bannerContainerRef.value && imageLoaded.value) {
    handleImageLoad()
  }
}

// 拖拽相关变量
let dragging = false
let startX = 0
let startY = 0
let originX = 0
let originY = 0

// 拖拽开始
const handleButtonMouseDown = (event: MouseEvent) => {
  if (!(props.edit ?? true)) return
  if (!buttonVisible.value) return

  dragging = true
  startX = event.clientX
  startY = event.clientY
  originX = buttonConfig.value.x
  originY = buttonConfig.value.y
  isDragging.value = true

  window.addEventListener('mousemove', handleMouseMove)
  window.addEventListener('mouseup', handleMouseUp)
  event.preventDefault()
}

// 获取按钮的实际渲染尺寸（考虑缩放）
const getButtonDimensions = () => {
  if (!buttonRef.value) {
    // 如果无法获取实际尺寸，使用基于字体大小的估算
    const config = buttonConfig.value
    const fontSize = config.fontSize
    const textLength = buttonText.value.length

    // 基于字体大小和文字长度估算按钮尺寸
    const estimatedWidth = Math.max(textLength * fontSize * 0.8 + 48, 80) // 48px为左右padding
    const estimatedHeight = fontSize + 18 // 18px为上下padding

    return {
      width: estimatedWidth,
      height: estimatedHeight
    }
  }

  // 获取按钮实际渲染尺寸，转换为设计尺寸坐标系
  const rect = buttonRef.value.getBoundingClientRect()
  const currentScale = scale.value || 1

  return {
    width: rect.width / currentScale,
    height: rect.height / currentScale
  }
}

// 计算有效的边界范围
const getBoundaryLimits = () => {
  const { width: buttonWidth, height: buttonHeight } = getButtonDimensions()

  // 获取当前图片和容器的实际尺寸
  const imageWidth = imageDimensions.value.width || DESIGN_WIDTH
  const imageHeight = imageDimensions.value.height || DESIGN_HEIGHT
  const containerWidth = containerDimensions.value.width || DESIGN_WIDTH
  const containerHeight = containerDimensions.value.height || DESIGN_HEIGHT

  // 计算图片在容器中的实际显示区域（考虑object-cover的效果）
  const imageAspectRatio = imageWidth / imageHeight
  const containerAspectRatio = containerWidth / containerHeight

  let effectiveWidth, effectiveHeight

  if (imageAspectRatio > containerAspectRatio) {
    // 图片比容器更宽，高度填满容器，宽度被裁剪
    effectiveHeight = containerHeight
    effectiveWidth = effectiveHeight * imageAspectRatio
  } else {
    // 图片比容器更高或相等，宽度填满容器，高度被裁剪
    effectiveWidth = containerWidth
    effectiveHeight = effectiveWidth / imageAspectRatio
  }

  // 转换为设计坐标系
  const currentScale = scale.value || 1
  const designEffectiveWidth = effectiveWidth / currentScale
  const designEffectiveHeight = effectiveHeight / currentScale

  // 计算按钮可移动的边界（考虑按钮中心点定位）
  // 按钮使用 transform: translate(-50%, -50%)，所以中心点就是定位点
  const halfButtonWidth = buttonWidth / 2
  const halfButtonHeight = buttonHeight / 2

  const minX = halfButtonWidth
  const maxX = designEffectiveWidth - halfButtonWidth
  const minY = halfButtonHeight
  const maxY = designEffectiveHeight - halfButtonHeight

  const result = {
    minX: Math.max(0, minX),
    maxX: Math.max(minX, maxX),
    minY: Math.max(0, minY),
    maxY: Math.max(minY, maxY),
    effectiveWidth: designEffectiveWidth,
    effectiveHeight: designEffectiveHeight,
    buttonWidth,
    buttonHeight,
    containerWidth,
    containerHeight,
    imageWidth,
    imageHeight,
    scale: currentScale
  }
  return result
}

// 限制坐标在边界内
const clampToBoundary = (x: number, y: number) => {
  const limits = getBoundaryLimits()

  const clampedX = Math.max(limits.minX, Math.min(x, limits.maxX))
  const clampedY = Math.max(limits.minY, Math.min(y, limits.maxY))

  return { x: clampedX, y: clampedY }
}

// 拖拽移动
const handleMouseMove = (event: MouseEvent) => {
  if (!dragging) return

  const dx = (event.clientX - startX) / (scale.value || 1)
  const dy = (event.clientY - startY) / (scale.value || 1)

  // 计算新位置
  const newX = originX + dx
  const newY = originY + dy

  // 应用边界限制
  const { x: clampedX, y: clampedY } = clampToBoundary(newX, newY)

  updateButtonPosition(Math.round(clampedX), Math.round(clampedY))
}

// 拖拽结束
const handleMouseUp = () => {
  if (!dragging) return

  dragging = false
  isDragging.value = false
  window.removeEventListener('mousemove', handleMouseMove)
  window.removeEventListener('mouseup', handleMouseUp)
}

// 更新按钮位置（带边界检查）
const updateButtonPosition = (x: number, y: number) => {
  // 应用边界限制
  const { x: clampedX, y: clampedY } = clampToBoundary(x, y)

  const banner = { ...props.banner }
  if (!banner.button) banner.button = {}

  banner.button.x = clampedX
  banner.button.y = clampedY
  emit('update:banner', banner)
}

// 获取当前边界限制信息（供外部组件使用）
const getBoundaryInfo = () => {
  const limits = getBoundaryLimits()

  return {
    minX: limits.minX,
    maxX: limits.maxX,
    minY: limits.minY,
    maxY: limits.maxY,
    effectiveWidth: limits.effectiveWidth,
    effectiveHeight: limits.effectiveHeight,
    buttonWidth: limits.buttonWidth,
    buttonHeight: limits.buttonHeight,
    containerWidth: limits.containerWidth,
    containerHeight: limits.containerHeight,
    imageWidth: limits.imageWidth,
    imageHeight: limits.imageHeight,
    scale: limits.scale
  }
}

// 暴露边界信息给父组件
defineExpose({
  getBoundaryInfo
})

// 预览区块点击事件处理
const handlePreviewClick = (event: Event) => {
  // 只在编辑模式下处理预览区块点击
  if (props.edit ?? true) {
    event.stopPropagation()
    emit('click')
  }
}

// 按钮点击事件处理
const handleButtonClick = (event: Event) => {
  // 如果是编辑模式，不执行跳转
  if (props.edit ?? true) {
    // 阻止事件冒泡到预览区块
    event.stopPropagation()
    return
  }

  const link = props.banner?.button?.link

  // 如果没有设置链接或链接为空，不执行任何操作
  if (!link || link.trim() === '' || link === '#') {
    return
  }

  // 阻止事件冒泡
  event.stopPropagation()
  event.preventDefault()

  try {
    // 判断是否为外部链接（http/https）
    if (link.startsWith('http://') || link.startsWith('https://')) {
      // 外部链接在新窗口打开
      window.open(link, '_blank', 'noopener,noreferrer')
    } else {
      // 内部路由使用 Vue Router 导航
      router.push(link)
    }
  } catch (error) {
    console.error($t('competition.modules.banner.jumpFailed'), error)
  }
}

// 使用 ResizeObserver 监听容器尺寸变化
let resizeObserver: ResizeObserver | null = null

const setupResizeObserver = () => {
  if (!bannerContainerRef.value) return

  // 清理之前的观察器
  if (resizeObserver) {
    resizeObserver.disconnect()
  }

  // 创建新的 ResizeObserver 来监听容器尺寸变化
  resizeObserver = new ResizeObserver(() => {
    // 当容器尺寸变化时重新计算尺寸
    if (imageLoaded.value) {
      handleImageLoad()
    }
  })

  // 开始观察banner容器
  resizeObserver.observe(bannerContainerRef.value)
}

// 生命周期钩子
onMounted(() => {
  // 使用 nextTick 确保 DOM 已渲染
  nextTick(() => {
    setupResizeObserver()
  })
  window.addEventListener('resize', recalculateDimensions)
})

onUnmounted(() => {
  if (resizeObserver) {
    resizeObserver.disconnect()
    resizeObserver = null
  }
  window.removeEventListener('resize', recalculateDimensions)
  window.removeEventListener('mousemove', handleMouseMove)
  window.removeEventListener('mouseup', handleMouseUp)
})

// 监听bannerUrl变化
watch(bannerUrl, (newUrl) => {
  if (newUrl) {
    loadImage(newUrl)
  } else {
    imageUrl.value = ''
    imageLoaded.value = false
  }
}, { immediate: true })

// 监听edit模式变化，确保容器尺寸变化时重新计算
watch(() => props.edit, () => {
  // 使用 nextTick 确保 DOM 更新后再重新计算
  nextTick(() => {
    recalculateDimensions()
  })
})


</script>

<style scoped>
/* 预览区块激活状态样式 */
.preview-block-active {
  border: 1px dashed #000000;
  transition: border 0.3s ease;
}
</style>
